package com.smart.community.property.controller;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.smart.community.commons.result.PageResult;
import com.smart.community.commons.result.Result;
import com.smart.community.property.dto.BatchPropertyFeeDTO;
import com.smart.community.property.dto.PropertyFeeDTO;
import com.smart.community.property.dto.PropertyFeeEditDTO;
import com.smart.community.property.dto.PropertyFeeGenerateDTO;
import com.smart.community.property.service.IPropertyService;
import com.smart.community.property.vo.PropertyFeeStatisticsVO;
import com.smart.community.property.vo.PropertyFeeVO;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;

/**
 * 物业费管理控制器
 * 
 * @author Wu.Liang
 * @since 2025-06-26
 * @version 2.0.0
 */
@RestController
@RequestMapping("/property/property-fees")
@Tag(name = "物业费管理", description = "物业费账单生成、查询、统计、催缴等接口")
@Slf4j
public class PropertyFeeController {

	@Autowired
	private IPropertyService propertyService;

	/**
	 * 分页查询物业费账单
	 * 
	 * @author Wu.Liang
	 */
	@GetMapping
	@Operation(summary = "分页查询物业费账单", description = "支持按社区、状态等条件查询")
	public Result<PageResult<PropertyFeeVO>> getPropertyFeeList(
			@Parameter(description = "查询条件") PropertyFeeDTO propertyFeeDTO) throws Exception {
		PageResult<PropertyFeeVO> result = propertyService.pagePropertyBills(propertyFeeDTO);
		return Result.success("查询成功", result);
	}

	/**
	 * 查询当前用户的物业费账单
	 * 
	 * @author Wu.Liang
	 */
	@GetMapping("/my-fees")
	@Operation(summary = "查询当前用户的物业费账单", description = "根据当前登录用户ID查询业主信息，获取关联的房户ID集合，查询相关物业费账单")
	public Result<PageResult<PropertyFeeVO>> getMyPropertyFees(
			@Parameter(description = "当前页") @RequestParam(defaultValue = "1") Integer current,
			@Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Integer size,
			@Parameter(description = "缴费状态：0-未缴费，1-已缴费，2-逾期，3-部分缴费") @RequestParam(required = false) Integer paymentStatus,
			@Parameter(description = "费用类型：1-物业费，2-水费，3-电费，4-燃气费，5-卫生费") @RequestParam(required = false) Integer feeType,
			@Parameter(description = "计费周期") @RequestParam(required = false) String billingPeriod) {
		try {
			log.info("查询当前用户的物业费账单，当前页: {}, 每页大小: {}, 缴费状态: {}, 费用类型: {}, 计费周期: {}", 
					current, size, paymentStatus, feeType, billingPeriod);
			PageResult<PropertyFeeVO> result = propertyService.getMyPropertyFees(current, size, paymentStatus, feeType, billingPeriod);
			log.info("查询当前用户的物业费账单成功，返回记录数: {}", result.getRecords().size());
			return Result.success("查询成功", result);
		} catch (Exception e) {
			log.error("查询当前用户的物业费账单失败，错误信息: {}", e.getMessage(), e);
			return Result.fail("查询失败：" + e.getMessage());
		}
	}

	/**
	 * 获取费用详情
	 * 
	 * @author Wu.Liang
	 */
	@GetMapping("/detail/{billId}")
	@Operation(summary = "获取费用详情", description = "获取指定账单的详细信息")
	public Result<PropertyFeeVO> getBillDetail(@Parameter(description = "账单ID") @PathVariable Long billId) {
		try {
			log.info("获取费用详情，账单ID: {}", billId);
			PropertyFeeVO detail = propertyService.getPropertyFeeDetail(billId);
			log.info("获取费用详情成功，账单ID: {}", billId);
			return Result.success("查询成功", detail);
		} catch (Exception e) {
			log.error("获取费用详情失败，账单ID: {}, 错误信息: {}", billId, e.getMessage(), e);
			return Result.fail("获取详情失败：" + e.getMessage());
		}
	}

	/**
	 * 更新费用信息
	 * 
	 * @author Wu.Liang
	 */
	@PutMapping("/update/{billId}")
	@Operation(summary = "更新费用信息", description = "更新指定账单的信息")
	public Result<Boolean> updateBill(@Parameter(description = "账单ID") @PathVariable Long billId,
			@Parameter(description = "费用信息") @RequestBody @Valid PropertyFeeDTO propertyFeeDTO) {
		try {
			log.info("更新费用信息，账单ID: {}, 更新数据: {}", billId, propertyFeeDTO);
			boolean success = propertyService.updatePropertyFee(billId, propertyFeeDTO);
			log.info("更新费用信息成功，账单ID: {}", billId);
			return Result.success("更新成功", success);
		} catch (Exception e) {
			log.error("更新费用信息失败，账单ID: {}, 错误信息: {}", billId, e.getMessage(), e);
			return Result.fail("更新失败：" + e.getMessage());
		}
	}

	/**
	 * 编辑物业费信息（仅允许编辑指定字段）
	 * 
	 * @author Wu.Liang
	 */
	@PutMapping("/edit/{billId}")
	@Operation(summary = "编辑物业费信息", description = "编辑物业费信息，仅允许编辑费用金额、缴费状态，到期日期不允许修改")
	public Result<Boolean> editPropertyFee(@Parameter(description = "账单ID") @PathVariable Long billId,
			@Parameter(description = "编辑信息") @RequestBody @Valid PropertyFeeEditDTO editDTO) {
		try {
			log.info("编辑物业费信息，账单ID: {}, 编辑数据: {}", billId, editDTO);
			boolean success = propertyService.editPropertyFee(billId, editDTO);
			log.info("编辑物业费信息成功，账单ID: {}", billId);
			return Result.success("编辑成功", success);
		} catch (Exception e) {
			log.error("编辑物业费信息失败，账单ID: {}, 错误信息: {}", billId, e.getMessage(), e);
			return Result.fail("编辑失败：" + e.getMessage());
		}
	}

	/**
	 * 缴费
	 * 
	 * @author Wu.Liang
	 */
	@PostMapping("/pay/{billId}")
	@Operation(summary = "缴费", description = "为指定账单进行缴费操作")
	public Result<Boolean> payBill(@Parameter(description = "账单ID") @PathVariable Long billId,
			@Parameter(description = "支付金额") @RequestParam BigDecimal paymentAmount,
			@Parameter(description = "支付方式") @RequestParam String paymentMethod) {
		try {
			log.info("缴费操作，账单ID: {}, 支付金额: {}, 支付方式: {}", billId, paymentAmount, paymentMethod);
			boolean success = propertyService.payBill(billId, paymentAmount, paymentMethod);
			log.info("缴费操作成功，账单ID: {}", billId);
			return Result.success("缴费成功", success);
		} catch (Exception e) {
			log.error("缴费操作失败，账单ID: {}, 错误信息: {}", billId, e.getMessage(), e);
			return Result.fail("缴费失败：" + e.getMessage());
		}
	}

	/**
	 * App端专用缴费接口
	 * 
	 * @author Wu.Liang
	 */
	@PostMapping("/pay")
	@Operation(summary = "App端缴费", description = "App端专用缴费接口，支持JSON格式传参")
	public Result<Map<String, Object>> payFee(@Parameter(description = "缴费信息") @RequestBody Map<String, Object> payData) {
		try {
			Long feeId = Long.valueOf(payData.get("feeId").toString());
			BigDecimal paymentAmount = new BigDecimal(payData.get("paymentAmount").toString());
			String paymentMethod = payData.get("paymentMethod").toString();
			
			log.info("App端缴费操作，费用ID: {}, 支付金额: {}, 支付方式: {}", feeId, paymentAmount, paymentMethod);
			boolean success = propertyService.payBill(feeId, paymentAmount, paymentMethod);
			
			if (success) {
				Map<String, Object> result = new HashMap<>();
				result.put("success", true);
				result.put("orderNo", "PAY" + System.currentTimeMillis());
				result.put("paymentAmount", paymentAmount);
				result.put("paymentMethod", paymentMethod);
				
				log.info("App端缴费操作成功，费用ID: {}", feeId);
				return Result.success("缴费成功", result);
			} else {
				return Result.fail("缴费失败");
			}
		} catch (Exception e) {
			log.error("App端缴费操作失败，错误信息: {}", e.getMessage(), e);
			return Result.fail("缴费失败：" + e.getMessage());
		}
	}

	/**
	 * 获取缴费记录
	 * 
	 * @author Wu.Liang
	 */
	@GetMapping("/payment-records")
	@Operation(summary = "获取缴费记录", description = "获取指定费用的缴费记录")
	public Result<List<Map<String, Object>>> getPaymentRecords(@Parameter(description = "费用ID") @RequestParam Long feeId) {
		try {
			log.info("获取缴费记录，费用ID: {}", feeId);
			
			// 模拟缴费记录数据
			List<Map<String, Object>> records = new ArrayList<>();
			
			// 这里应该从数据库查询真实的缴费记录
			// 暂时返回模拟数据
			Map<String, Object> record1 = new HashMap<>();
			record1.put("id", 1L);
			record1.put("paymentAmount", new BigDecimal("8000.00"));
			record1.put("paymentTime", "2025-01-15 10:30:00");
			record1.put("paymentMethod", "微信支付");
			record1.put("status", 1); // 1-成功
			records.add(record1);
			
			log.info("获取缴费记录成功，费用ID: {}, 记录数: {}", feeId, records.size());
			return Result.success("查询成功", records);
		} catch (Exception e) {
			log.error("获取缴费记录失败，费用ID: {}, 错误信息: {}", feeId, e.getMessage(), e);
			return Result.fail("获取缴费记录失败：" + e.getMessage());
		}
	}

	/**
	 * 删除费用记录
	 * 
	 * @author Wu.Liang
	 */
	@DeleteMapping("/delete/{billId}")
	@Operation(summary = "删除费用记录", description = "删除指定的费用记录")
	public Result<Boolean> deleteBill(@Parameter(description = "账单ID") @PathVariable Long billId) {
		try {
			log.info("删除费用记录，账单ID: {}", billId);
			boolean success = propertyService.removeById(billId);
			log.info("删除费用记录成功，账单ID: {}", billId);
			return Result.success("删除成功", success);
		} catch (Exception e) {
			log.error("删除费用记录失败，账单ID: {}, 错误信息: {}", billId, e.getMessage(), e);
			return Result.fail("删除失败：" + e.getMessage());
		}
	}



	/**
	 * 生成物业费账单（支持计费月份时间段）
	 * 
	 * @author Wu.Liang
	 */
	@PostMapping("/generate")
	@Operation(summary = "生成物业费账单", description = "按社区和计费月份时间段批量生成物业费账单，将时间段内的费用合并为一份总费用单")
	public Result<Integer> generatePropertyFee(
			@Parameter(description = "生成参数") @RequestBody @Valid PropertyFeeGenerateDTO generateDTO) throws Exception {
		log.info("生成物业费账单（时间段），参数: {}", generateDTO);

		int count = propertyService.generatePropertyFeeByRange(generateDTO.getCommunityId(),
				generateDTO.getBillingMonthRange(), generateDTO.getDueDate(), generateDTO.getRemark());

		return Result.success("生成成功", count);
	}

	/**
	 * 批量生成物业费账单
	 * 
	 * @author Wu.Liang
	 */
	@PostMapping("/batch-generate")
	@Operation(summary = "批量生成物业费账单", description = "支持多个社区同时生成账单")
	public Result<Map<String, Integer>> batchGeneratePropertyFee(
			@Parameter(description = "批量生成参数") @RequestBody BatchPropertyFeeDTO batchDTO) throws Exception {
		log.info("批量生成物业费账单，参数: {}", batchDTO);
		Map<String, Integer> result = propertyService.batchGeneratePropertyBills(batchDTO);
		return Result.success("批量生成成功", result);
	}



	/**
	 * 批量发送催缴提醒
	 * 
	 * @author Wu.Liang
	 */
	@PostMapping("/batch-remind")
	@Operation(summary = "批量发送催缴提醒", description = "批量向逾期用户发送催缴提醒")
	public Result<Map<String, Integer>> batchSendReminder(
			@Parameter(description = "社区ID") @RequestParam Long communityId,
			@Parameter(description = "提醒方式：sms-短信，email-邮件，app-APP推送") @RequestParam String remindType)
			throws Exception {
		log.info("批量发送催缴提醒，社区ID: {}, 提醒方式: {}", communityId, remindType);
		Map<String, Integer> result = propertyService.batchSendPaymentReminder(communityId, remindType);
		return Result.success("批量提醒发送成功", result);
	}

	/**
	 * 获取物业费统计信息
	 * 
	 * @author Wu.Liang
	 */
	@GetMapping("/statistics")
	@Operation(summary = "获取物业费统计信息", description = "获取指定社区的物业费收缴统计")
	public Result<PropertyFeeStatisticsVO> getPropertyFeeStatistics(
			@Parameter(description = "社区ID") @RequestParam Long communityId,
			@Parameter(description = "年份") @RequestParam(defaultValue = "#{T(java.time.LocalDate).now().getYear()}") Integer year)
			throws Exception {
		log.info("获取物业费统计信息，社区ID: {}, 年份: {}", communityId, year);
		PropertyFeeStatisticsVO statistics = propertyService.getPropertyFeeStatistics(communityId, year);
		return Result.success("查询成功", statistics);
	}

	/**
	 * 获取物业费月度统计
	 * 
	 * @author Wu.Liang
	 */
	@GetMapping("/statistics/monthly")
	@Operation(summary = "获取物业费月度统计", description = "获取指定社区的物业费月度收缴统计")
	public Result<List<PropertyFeeStatisticsVO>> getMonthlyPropertyFeeStatistics(
			@Parameter(description = "社区ID") @RequestParam Long communityId,
			@Parameter(description = "年份") @RequestParam(defaultValue = "#{T(java.time.LocalDate).now().getYear()}") Integer year)
			throws Exception {
		log.info("获取物业费月度统计，社区ID: {}, 年份: {}", communityId, year);
		List<PropertyFeeStatisticsVO> statistics = propertyService.getMonthlyPropertyFeeStatistics(communityId, year);
		return Result.success("查询成功", statistics);
	}

	/**
	 * 查询用户未缴费账单
	 * 
	 * @author Wu.Liang
	 */
	@GetMapping("/user/{userId}/unpaid")
	@Operation(summary = "查询用户未缴费账单", description = "获取指定用户的所有未缴费账单")
	public Result<List<PropertyFeeVO>> getUnpaidBillsByUserId(
			@Parameter(description = "用户ID") @PathVariable Long userId) throws Exception {
		log.info("查询用户未缴费账单，用户ID: {}", userId);
		List<PropertyFeeVO> bills = propertyService.getUnpaidBillsByUserId(userId);
		return Result.success("查询成功", bills);
	}

	/**
	 * 导出物业费账单
	 * 
	 * @author Wu.Liang
	 */
	@GetMapping("/export")
	@Operation(summary = "导出物业费账单", description = "导出物业费账单到Excel文件")
	public Result<String> exportPropertyFeeBills(@Parameter(description = "查询条件") PropertyFeeDTO propertyFeeDTO)
			throws Exception {
		log.info("导出物业费账单，查询条件: {}", propertyFeeDTO);
		String filePath = propertyService.exportPropertyFeeBills(propertyFeeDTO);
		return Result.success("导出成功", filePath);
	}

	/**
	 * 清除物业费缓存
	 * 
	 * @author Wu.Liang
	 */
	@PostMapping("/cache/clear")
	@Operation(summary = "清除物业费缓存", description = "清除指定社区的物业费相关缓存")
	public Result<Void> clearPropertyFeeCache(@Parameter(description = "社区ID") @RequestParam Long communityId)
			throws Exception {
		log.info("清除物业费缓存，社区ID: {}", communityId);
		propertyService.clearPropertyFeeCache(communityId);
		return Result.success();
	}

	/**
	 * 清除用户物业费缓存
	 * 
	 * @author Wu.Liang
	 */
	@PostMapping("/cache/clear/user/{userId}")
	@Operation(summary = "清除用户物业费缓存", description = "清除指定用户的物业费相关缓存")
	public Result<Void> clearUserPropertyFeeCache(@Parameter(description = "用户ID") @PathVariable Long userId)
			throws Exception {
		log.info("清除用户物业费缓存，用户ID: {}", userId);
		propertyService.clearUserPropertyFeeCache(userId);
		return Result.success();
	}
}